﻿using System;
using System.Drawing;
using System.Windows.Forms;
using AForge.Video;
using AForge.Video.DirectShow;
using AForge.Vision.Motion;
using System.Collections.Generic;
using System.Windows.Forms.DataVisualization.Charting;
using System.Threading;
using AForge.Imaging;

namespace Analizador_de_Semillas
{
    public partial class MainForm : Form
    {
        static FilterInfoCollection camara;
        static VideoCaptureDevice capturaUno = null;
        static VideoCaptureDevice capturaDos = null;
        static MotionDetector detectorUno = new MotionDetector(new SimpleBackgroundModelingDetector()
            , new BlobCountingObjectsProcessing());
        static MotionDetector detectorDos = new MotionDetector(new SimpleBackgroundModelingDetector()
            , new BlobCountingObjectsProcessing());
        static double[] x = new double[256];
        static AutoResetEvent camera1Acquired = null;
        static AutoResetEvent camera2Acquired = null;
        static BlobCountingObjectsProcessing countingDetector = null;
        static BlobCountingObjectsProcessing countingDetectorDos = null;

        public MainForm()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            camara = new FilterInfoCollection(FilterCategory.VideoInputDevice);
            if (camara.Count == 0)
            {
                MessageBox.Show("No hay dispositivos disponibles!!", "Alerta", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                this.Close();
            }
            else
            {

                capturaUno = new VideoCaptureDevice(camara[0].MonikerString);

                videoSource.VideoSource = new AsyncVideoSource(capturaUno);
                videoSource.Start();

                capturaDos = new VideoCaptureDevice(camara[1].MonikerString);

                videoSourceUno.VideoSource = new AsyncVideoSource(capturaDos);
                videoSourceUno.Start();

                for (int i = 0; i < 256; i++)
                {
                    x[i] = i;
                }

                camera1Acquired = new AutoResetEvent(false);
                camera2Acquired = new AutoResetEvent(false);
            }

            Label.CheckForIllegalCrossThreadCalls = false;
        }

        private void videoSource_NewFrame(object sender, ref Bitmap image)
        {
            lock (this)
            {
                if (detectorUno != null && detectorDos != null)
                {
                    float motionLevel = detectorUno.ProcessFrame(image);

                    if (motionLevel > 0.2)
                    {
                        // check objects' count
                        
                        if (bw.IsBusy != true)
                        {
                            countingDetector = (BlobCountingObjectsProcessing)detectorUno.MotionProcessingAlgorithm;
                            countingDetectorDos = (BlobCountingObjectsProcessing)detectorDos.MotionProcessingAlgorithm;

                            bw.RunWorkerAsync();
                        }
                       

                        camera1Acquired.Set();
                    }
                }
            }
        }

        private void videoSourceUno_NewFrame(object sender, ref Bitmap image)
        {
            lock (this)
            {
                if (detectorUno != null && detectorDos != null)
                {
                    float motionLevel = detectorDos.ProcessFrame(image);

                    if (motionLevel > 0.2)
                    {
                        if (bw.IsBusy != true)
                        {
                            // check objects' count
                            countingDetector = (BlobCountingObjectsProcessing)detectorUno.MotionProcessingAlgorithm;
                            countingDetectorDos = (BlobCountingObjectsProcessing)detectorDos.MotionProcessingAlgorithm;

                            camera2Acquired.Set();
                        }
                        
                    }
                }
            }
        }

        private void CerrarCamaras()
        {
            videoSource.SignalToStop();
            videoSourceUno.SignalToStop();
            videoSourceUno.WaitForStop();
            videoSource.WaitForStop();

            if (detectorUno != null)
            {
                detectorUno.Reset();
            }

            if (detectorDos != null)
            {
                detectorDos.Reset();
            }

            this.Dispose();
            this.Close();
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            CerrarCamaras();
        }

        private void bw_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            if (countingDetector.ObjectsCount > 0 && countingDetectorDos.ObjectsCount > 0)
            {
                double sumH = 0;
                double sumW = 0;
                double cant = 0;

                foreach (var item in countingDetector.ObjectRectangles)
                {
                    sumH += item.Height;

                    sumW += item.Width;

                    cant++;
                }

                foreach (var item in countingDetectorDos.ObjectRectangles)
                {
                    sumH += item.Height;

                    sumW += item.Width;

                    cant++;
                }

                this.lblObjetos.Text = Math.Round((cant / 2),2).ToString();
                this.lblWidth.Text = Math.Round((sumW / cant) * 0.02645833333333, 2).ToString();
                this.lblHeight.Text = Math.Round((sumH / cant) * 0.02645833333333, 2).ToString();

                Color tempColor;
                double sumR = 0;
                double sumG = 0;
                double sumB = 0;
                double cantPix = 0;

                Bitmap picUno = videoSource.GetCurrentVideoFrame();
                Bitmap picDos = videoSourceUno.GetCurrentVideoFrame();

                for (int i = 0; i < picUno.Height; i++)
                {
                    for (int j = 0; j < picUno.Width; j++)
                    {
                        tempColor = picUno.GetPixel(j, i);
                        sumR += Convert.ToInt32(tempColor.R);
                        sumG += Convert.ToInt32(tempColor.G);
                        sumB += Convert.ToInt32(tempColor.B);
                        cantPix++;
                    }
                }

                for (int i = 0; i < picDos.Height; i++)
                {
                    for (int j = 0; j < picDos.Width; j++)
                    {
                        tempColor = picDos.GetPixel(j, i);
                        sumR += Convert.ToInt32(tempColor.R);
                        sumG += Convert.ToInt32(tempColor.G);
                        sumB += Convert.ToInt32(tempColor.B);
                        cantPix++;
                    }
                }

                lblPorcR.Text = Math.Round((sumR / cantPix / 255) * 100, 2).ToString();
                lblPorcB.Text = Math.Round((sumB / cantPix / 255) * 100, 2).ToString();
                lblPorcG.Text = Math.Round((sumG / cantPix / 255) * 100, 2).ToString();

                ImageStatistics rgbStatisticsUno = new ImageStatistics(picUno);

                ImageStatistics rgbStatisticsDos = new ImageStatistics(picDos);

                Series red = new Series();
                int x = 0;
                for (int i = rgbStatisticsUno.Red.Min; i < rgbStatisticsUno.Red.Max; i++)
                {
                    red.Points.AddXY(x, (rgbStatisticsUno.Red.Values[i] + rgbStatisticsDos.Red.Values[i]) / 2);
                    x++;
                }

                Series blue = new Series();
                x = 0;
                for (int i = rgbStatisticsUno.Blue.Min; i < rgbStatisticsUno.Blue.Max; i++)
                {
                    blue.Points.AddXY(x, (rgbStatisticsUno.Blue.Values[i] + rgbStatisticsDos.Blue.Values[i]) / 2);
                    x++;
                }

                Series green = new Series();
                x = 0;
                for (int i = rgbStatisticsUno.Green.Min; i < rgbStatisticsUno.Green.Max; i++)
                {
                    green.Points.AddXY(x, (rgbStatisticsUno.Green.Values[i] + rgbStatisticsDos.Green.Values[i]) / 2);
                    x++;
                }

                if (chrHistogramaRojo.Series.Count > 0) chrHistogramaRojo.Series.Clear();
                chrHistogramaRojo.Series.Add(red);
                chrHistogramaRojo.Series[0].Color = Color.Red;

                if (chrHistogramaAzul.Series.Count > 0) chrHistogramaAzul.Series.Clear();
                chrHistogramaAzul.Series.Add(blue);
                chrHistogramaAzul.Series[0].Color = Color.Blue;

                if (chrHistogramaVerde.Series.Count > 0) chrHistogramaVerde.Series.Clear();
                chrHistogramaVerde.Series.Add(green);
                chrHistogramaVerde.Series[0].Color = Color.Green;
            }
        }

        private void lblRegion_Click(object sender, EventArgs e)
        {
            DetectarRegion dtr = new DetectarRegion(this.videoSource.GetCurrentVideoFrame());

            dtr.FormClosed += new FormClosedEventHandler(dtr_FormClosed); 

            dtr.Show();
        }

        void dtr_FormClosed(object sender, FormClosedEventArgs e)
        {
            detectorUno.MotionZones = DetectarRegion.pasarZona();
        }

        private void lblRegionDos_Click(object sender, EventArgs e)
        {
            DetectarRegion dt = new DetectarRegion(this.videoSourceUno.GetCurrentVideoFrame());

            dt.FormClosed += new FormClosedEventHandler(dt_FormClosed);

            dt.Show();
        }

        void dt_FormClosed(object sender, FormClosedEventArgs e)
        {
            detectorDos.MotionZones = DetectarRegion.pasarZona();
        }
    }
}
